package com.cskaoyan.javase.oop3._1interface._1basic;

import com.cskaoyan.javase.oop3._1interface._0introduction.Demo;

import javax.print.attribute.standard.PrinterURI;

/**
 * 接口的特点我们主要研究以下方面
 * 1. 接口的声明特点
 *      思考：接口能不能创建对象？
 *      接口是不能创建对象的
 *      接口声明中本身就隐含关键字“abstract”接口本身就是抽象的
 *      既然接口是抽象的，不能创建对象，那么定义接口的目的就是为了实现
 *      所以接口的声明中不能写关键字“final”
 *
 * 2. 接口的实现类的书写格式
 *      接口的目的就是为了实现，所以我们经常写接口的实现类
 *      很多时候接口的实现类，推荐命名为“接口名 + Impl”
 *      并且如果实现类就写在接口附近
 *      那么就在接口的包下创建一个新的包叫"impl"，把实现类放进去。
 *      当然这也不是强制的，你不写也都可以。
 *
 * 3. 成员特点
 * 接口不是类，它的成员和类的成员差别很大。
 * 接口中所有能写出来的变量方法,默认全都是public修饰的,而且权限不可更改!
 *    1.成员
 *      a.定义变量
 *          接口中的变量默认都是public static final修饰的全局常量
 *          接口中没有变量,都是全局常量
 *          并且访问权限一定是public,不可更改
 *          接口侧重于描述行为,几乎不描述属性
 *          接口中绝大情况下不需要属性,只有当接口的所有子类都需要共用一个全局常量时,可以考虑定义全局常量(这种场景几乎没有,很少见)
 *          所以接口中尽量不要定义变量,如果要定义按以下格式写:
 *          [数据类型] 变量名 = 值;
 *          隐含的关键字不要写出来.
 *          并且接口中没有静态代码块,只能直接显式赋值.
 *
 *      b.定义方法
 *          接口中的方法默认都是public abstract修饰的公共的,抽象方法.
 *          语法:
 *          返回值类型 方法名(形参列表);
 *          隐含的修饰符不要写出来
 *
 *          在Java8之前,接口中的所有方法都是抽象方法,接口中没有实现(带有方法体的)方法.
 *          在Java8中,接口中新增了两种实现方法:
 *              1.默认实现方法
 *              2.静态方法
 *           这两种方法都仅做了解,实际开发用途不大.
 *
 *
 *   1.接口中的默认实现方法
 *   语法:
 *      default 返回值类型 方法名(形参列表){
 *          // 方法体
 *      }
 *     注意: 这个方法的访问权限隐含为public,不可更改
 *    接口中的默认方法,和类中的成员方法类似
 *    需要创建对象,然后才能调用它
 *    接口没有对象,接口的实现类对象可以调用这个方法
 *    Java8之所以引入默认方法,主要是两点原因:
 *          1.为了代码的兼容性考虑,新增默认实现方法,不需要所有子类都实现.避免麻烦.
 *          2.主要是为了和Java8的新特性Lambda表达式以及Stream API配合使用(后面再说)
 *
 *    建议大家在日常开发中,尽量避免在接口中写实现方法
 *    大家普遍见到的接口,往往都十分简洁.里面只有抽象方法
 *
 *  2.接口中的静态方法
 *  语法:
 *      static 返回值类型 方法名(形参列表){
 *          // 方法体
 *      }
 * 和默认实现方法类似,静态方法的出现,也主要是为了配合Lambda表达式 Stream API等
 * 建议大家不要自己在接口中定义静态方法.
 * 注意事项:
 *      1.静态方法,使用接口名点调用
 *      2.接口中的静态方法,不允许用子类类名调用
 *      3.静态方法的访问权限也默认是public,不可更改
 *      4.小tips:
 *          Java8之后,接口中甚至可以写main方法
 *          当然仅做了解,没啥用
 *
 * 4. 构造器
 *      接口有没有构造器?
 *      构造器要么自己用,要么给子类用?接口需要吗?
 *      接口不需要构造器,也用不上构造器
 *      接口是没有构造器这种结构的.
 *
 *      思考:
 *           1.接口没有构造器,那么接口的实现类的隐式子类对象初始化,指向的是谁?
 *              指向它的父类的,如果没有明确的父类,那就指向Object无参构造
 *           2.接口有没有继承Object?
 *              接口严格来说,是继承了Object的
 *              但实际上接口不能自己创建对象,所以创建接口子类对象时,子类本身就会继承Object
 *
 * 5. 代码块
 *      没有构造器,就没有构造代码块
 *      接口也没有静态代码块
 *
 * 以上总结，实际上接口的成员特点非常简单：
 *      1.变量。全部都是全局常量
 *      2.方法。正常全部都是抽象方法。特殊的可以定义实现方法
 *      3.构造器。没有
 *      3.代码块。没有
 *      接口是比较单纯的，常见的接口只有抽象方法的声明，没有别的东西。
 *
 *
 * 接口的子类，可以是什么？
 *      1.普通类。普通类实现接口必须实现所有的抽象方法。
 *      2.抽象类。无需实现抽象方法,当然想实现允许实现。
 *      3.接口。接口可以继承接口，使用关键字"extends"
 *
 * 总结，抽象类、普通类、接口之间的实现，继承关系：
 *      1.继承是不能跨越种族的。接口和接口继承，类与类之间继承。
 *      但是类的继承是单继承，不能直接继承多个类
 *      接口的继承是多继承，接口可以直接继承多个接口
 *
 *      2.实现发生在类与接口之间，类实现接口。
 *      3.但是接口与类没有任何关系。
 *
 *
 * @since 14:52
 * @author wuguidong@cskaoyan.onaliyun.com
 */
// Modifier 'abstract' is redundant for interfaces
public interface IDemo {
    /*public static void main(String[] args) {
        System.out.println("hello world!");
    }*/
    // Variable 'a' might not have been initialized
    // int a;
    // Modifier 'static' is redundant for interface fields
    // 不推荐的定义方式:
    //  static final int a = 10;
    // 推荐的定义方式:
    int a = 10;
    // static {
    //
    // }

    // 禁止的方法命名方式
    // public abstract void test();
    // 必须使用的方法命名方式
    void test();

    // 定义默认实现方法
    default void testDefault() {
        System.out.println("我是Java8之后,接口中的默认实现方法");
    }

    static void testStatic() {
        System.out.println("我是Java8之后,接口中的静态方法");
    }

}

// 日常最多见的接口
interface IA {
    void test1(int a);

    int test2();

    String test3(String name);
    // ...
}

interface IB extends IA {
}

interface IC extends IB, IDemo {
}

interface ID  {
}

interface IE {
}


